package org.abc.uiCore.list
{
	import de.polygonal.ds.DLL;
	import de.polygonal.ds.DLLNode;
	
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import org.abc.interfaces.IListView;
	import org.abc.uiCore.AbcBindView;
	import org.abc.uiCore.event.ListModelEvent;
	import org.abc.uiCore.vo.CpVo;
	import org.abc.uiCore.vo.ListVo;

	/**
	 * @describe  	横向列表显示对象
	 * @author  	Mr.zheng
	 * @website 	http://blog.sina.com.cn/zihua2007
	 * @time		2011-8-18 22:12
	 * 
	 * @todo		2011-10-17 需要增加动态添加、删除项
	 */
	public class AbcListView extends AbcBindView implements IListView
	{
		/** 总页码 */
		private var _totalPage:int;

		/**
		 * 
		 * @return 
		 */
		public function get totalPage():int
		{
			return _totalPage;
		}
		/** 当前页码 */
		private var _currentPage:int;

		/**
		 * 
		 * @return 
		 */
		public function get currentPage():int
		{
			return _currentPage;
		}
		/** 总个数 */
		private var _totalNum:int;

		/**
		 * 
		 * @return 
		 */
		public function get totalNum():int
		{
			return _totalNum;
		}

		/** cp类 */
		protected var _CP:Class;
		/** 数据源 */
		protected var _model:ListModel;
		/** 一页的个数 */
		protected var _pageNum:int;
		/** 间隔数 */
		protected var _gap:int;
		/** cp组成的链 */
		protected var _cpDll:DLL;
		/** 被点击的CP，如果跳到上一页，或者下一页之后，CP处于未被选择状态，_currCp依然不变 */
		private var _currCp:AbcCP;
		/** 排列方式 */
		protected var _align:int;

		//===================================================================================
		/* public function */
		/**
		 * @param	listVo.CP			列表中item显示对象
		 * @param	listVo.model		列表数据
		 * @param	listVo.pageNum		一页显示的个数
		 * @param	listVo.gap			item间距
		 * @param	listVo.align		0:横向，1:竖向
		 */
		public function setParams(listVo:ListVo):void
		{
			_CP=listVo.CP;
			_model=listVo.model;
			_pageNum=listVo.pageNum;
			_gap=listVo.gap;
			_align=listVo.align;

			_cpDll=new DLL();

			createCpDll(); //创建cp链
			showCp(); //根据cp链来显示
			initModelAndCps(); //初始化model和cp

			listVo.dispose();
		}

		/** 上一页 */
		public function prePage():void
		{
			gotoPage(_currentPage - 1);
		}

		/** 下一页 */
		public function nextPage():void
		{
			gotoPage(_currentPage + 1);
		}

		/**
		 * 显示第几页
		 * @param	num
		 */
		public function gotoPage(num:int):void
		{
			//是否能够显示该页
			var showPageNum:int=getCountForPage(num);
			if (showPageNum == -1)return;
			//该页cp初始化
			initCps();
			//切换页码
			_currentPage=num;
			//显示下一页内容
			updateCps();
		}

		/** override function */
		override protected function addStageEvent(e:Event):void
		{
			super.addStageEvent(e);

			_model.addEventListener(ListModelEvent.LISTMODEL_CHANGE, onListModelChange);
		}

		override protected function removeStageEvent(e:Event):void
		{
			super.removeStageEvent(e);

			_model.removeEventListener(ListModelEvent.LISTMODEL_CHANGE, onListModelChange);
		}
		override public function readyRecycle():void 
		{
			super.readyRecycle();
			initCps();
			_totalNum = 0;
			_totalPage = 0;
			_currentPage = 0;
			_pageNum = 0;
			_align = 0;
			_gap = 0;
			_currCp = null;
			_CP = null;
			_model.clear();
			_cpDll.clear();
			_model = null;
			_cpDll = null;
		}
		/* protected function */
		/**
		 * ListModel改变了[增加项|删除项]
		 * 如果改变之后的总页数大于当前页，显示当前页
		 * 如果改变之后的总页数小于当前页，显示最后一页
		 * @param	e
		 */
		protected function onListModelChange(e:ListModelEvent):void {
			_totalPage = Math.ceil(_model.size() / _pageNum);
			if(_totalPage>=_currentPage){
				gotoPage(_currentPage);
			}else {
				gotoPage(_totalPage);
			}
		}
		
		/**
		 * model更新，初始化cp,更新cp
		 * @param	e
		 */
		protected function initModelAndCps():void
		{
			_totalPage=Math.ceil(_model.size() / _pageNum);
			if (_totalPage <= 0)_totalPage=1;
			_currentPage=1;
			initCps();
			updateCps();
		}

		/** 更新当前所有cp的显示 */
		protected function updateCps():void
		{
			var node:DLLNode=getPointNode();
			var cpNode:DLLNode=_cpDll.head;
			var cp:AbcCP=cpNode.val as AbcCP;
			while (node && cpNode)
			{
				cp=cpNode.val as AbcCP;
				cp.update(node.val as CpVo);
				node=node.next;
				cpNode=cpNode.next;
				cp.addEventListener(MouseEvent.CLICK, onCpClick);
			}
		}

		/**
		 * 第num页的显示个数，-1为不合理
		 * @param	num
		 * @return
		 */
		protected function getCountForPage(num:int):int
		{
			if (num > _totalPage || num <= 0 || _totalPage <= 0)
				return -1; //排除不合理
			if (num < _totalPage)
				return _pageNum;
			if (num == _totalPage)
				return _totalNum % _pageNum;
			return -1;
		}

		/**
		 * 初始化当前页的CP
		 */
		protected function initCps():void
		{
			var cpNode:DLLNode=_cpDll.head;
			while (cpNode)
			{
				initCp(cpNode);
				cpNode=cpNode.next;
			}
		}

		/**
		 * 初始化指定node的CP
		 * @param	node
		 */
		protected function initCp(node:DLLNode):void
		{
			var cp:AbcCP=node.val as AbcCP;
			cp.reInit();
			cp.removeEventListener(MouseEvent.CLICK, onCpClick);
		}

		/**
		 * 获取当前页第一个nodel
		 * @return
		 */
		protected function getPointNode():DLLNode
		{
			//第一个	第二页		第三页
			//0			_pageNum	_pageNum*2
			return _model.getNodeAt((_currentPage - 1) * _pageNum);
		}

		/**
		 * 
		 * @param e
		 */
		protected function onCpClick(e:MouseEvent=null):void
		{
			var cp:AbcCP=e.currentTarget as AbcCP;
			var data:CpVo=cp.data;
			cp.selected=true;
			_model.selectedItem(data);

			/** 点击cp之后，只需要更新上一个被点击的cp显示，以及当前被点击cp的显示 */
			if (_currCp)
				_currCp.update();

			_currCp=cp;
			cp.update();
		}

		/**
		 * 
		 */
		protected function createCpDll():void
		{
			var cp:AbcCP;
			for (var i:int=0; i < _pageNum; i++)
			{
				cp=new _CP();
				_cpDll.append(cp);
			}
		}

		/** 初始化cp的位置 */
		protected function showCp():void
		{
			var nodel:DLLNode=_cpDll.head;
			var cp:AbcCP;
			var w:int=nodel.val.width;
			var h:int=nodel.val.height;
			var num:int;
			while (nodel)
			{
				cp=nodel.val as AbcCP;
				switch (_align)
				{
					case 0:
						cp.x=num * (w + _gap) + _gap;
						break;
					case 1:
						cp.y=num * (h + _gap) + _gap;
						break;
					default:
				}
				this.addChild(cp);
				nodel=nodel.next;
				num++;
			}
		}
		/**
		 * 根据vo获取对应的cp
		 * @time	2011-10-26 16:01
		 * @param	vo
		 * @return
		 */
		protected function getCpByVo(vo:CpVo):AbcCP {
			var index:int;
			var node:DLLNode = _model.head;
			var num:int = 0;
			var cp:AbcCP;
			while (node) 
			{
				if (node.val == vo) {
					index = num;
					cp = _cpDll.getNodeAt(index).val as AbcCP;
					return cp;
				}else {
					num++;
					node = node.next;
				}
			}
			return null;
		}
	/* private function */
	}
}
